package com.xzzz.irda.auth.server.authentication;

import cn.hutool.core.util.StrUtil;
import com.xzzz.irda.auth.core.authorization.Authorization;
import com.xzzz.irda.auth.core.constants.GrantTypeEnum;
import com.xzzz.irda.auth.core.exception.AuthException;
import com.xzzz.irda.auth.core.exception.AuthRCode;
import com.xzzz.irda.auth.core.AuthBaseProperties;
import com.xzzz.irda.auth.server.pojo.LoginMetadata;
import lombok.extern.slf4j.Slf4j;

/**
 * 请求类型划分
 *
 * @author wangyf
 *
 * @since 1.1.0 增加平台所属的APP标识
 */
@Slf4j
public class GrantTypeHandler {

    private final AuthBaseProperties authBaseProperties;

    public GrantTypeHandler(AuthBaseProperties authBaseProperties) {
        this.authBaseProperties = authBaseProperties;
    }

    /**
     * 授权方式标记
     */
    public Authorization createAuthorization(LoginMetadata login) {
        if (login == null) {
            throw new AuthException(AuthRCode.INVALID_GRANT_TYPE);
        }

        if (StrUtil.isBlank(login.getClientId()) || authBaseProperties.getClient(login.getClientId()) == null) {
            log.error("[AUTHORIZ] 登录失败,错误的客户端类型 > loginDTO:{}", login.toString());
            throw new AuthException(AuthRCode.INVALID_CLIENT_ID);
        }

        if (StrUtil.isBlank(login.getGrantType()) || !GrantTypeEnum.valid(login.getGrantType())) {
            log.error("[AUTHORIZ] 登录失败,错误的登录方式, 平台:{} ,登录方式:{}", login.getClientId(), login.getGrantType());
            throw new AuthException(AuthRCode.INVALID_GRANT_TYPE);
        }

        if (!authBaseProperties.getClient(login.getClientId()).getGrantType().contains(login.getGrantType())) {
            log.error("[AUTHORIZ] 登录失败,平台不允许该方式登录, 平台:{} ,登录方式:{}", login.getClientId(), login.getGrantType());
            throw new AuthException(AuthRCode.INVALID_GRANT_TYPE);
        }

        try {
            final String grantType = login.getGrantType().toLowerCase();
            Class<? extends Authorization> authClazz = GrantTypeEnum.getAuthorizationClass(grantType);

            // 授权类型不存在,则授权类型错误异常
            if (authClazz == null) {
                throw new AuthException(AuthRCode.INVALID_GRANT_TYPE);
            }
            Authorization authorization = authClazz.newInstance();

            // 授权类型/平台类型/客户端类型
            authorization.setGrantType(grantType);
            authorization.setClientId(login.getClientId());
            return authorization;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            throw new IllegalStateException("登录请求分类时发生未知错误");
        }
    }

}

